/****************************************************************************
 * Copyright (C) 2009-2010 SciTouch LLC
 * 
 * This file is part of Indigo toolkit.
 * 
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 3 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 * 
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

#ifndef __render_common_h__
#define __render_common_h__

typedef void* PVOID;

#include "base_cpp/tlscont.h"
#include "layout/metalayout.h"
struct Vec2f;
struct Edge;
class Molecule;
class Reaction;

enum DINGO_MODE {MODE_NONE, MODE_PDF, MODE_PNG, MODE_SVG, MODE_WMF, MODE_HDC, MODE_PRN, MODE_LAYOUT_MOL, MODE_LAYOUT_RXN};
enum INPUT_FORMAT {INPUT_FORMAT_UNKNOWN, INPUT_FORMAT_MOLFILE, INPUT_FORMAT_RXNFILE, INPUT_FORMAT_SMILES, INPUT_FORMAT_REACTION_SMILES};
enum LABEL_MODE {LABEL_MODE_NORMAL, LABEL_MODE_FORCESHOW, LABEL_MODE_HIDETERMINAL, LABEL_MODE_FORCEHIDE};
enum IMPLICIT_HYDROGEN_MODE {IHM_NONE, IHM_TERMINAL, IHM_HETERO, IHM_TERMINAL_HETERO, IHM_ALL};
enum {CWC_BASE = -2, CWC_WHITE=0, CWC_BLACK, CWC_RED, CWC_GREEN, CWC_BLUE, CWC_DARKGREEN, CWC_COUNT};
enum FONT_SIZE {FONT_SIZE_LABEL=0, FONT_SIZE_ATTR, FONT_SIZE_RGROUP_LOGIC, FONT_SIZE_RGROUP_LOGIC_INDEX, FONT_SIZE_INDICES, FONT_SIZE_COMMENT, FONT_SIZE_COUNT/*must be the last*/};
enum COMMENT_POS {COMMENT_POS_TOP, COMMENT_POS_BOTTOM};

// cos(a) to cos(a/2) 
double cos2c (const double cs);
// cos(a) to sin(a/2) 
double sin2c (const double cs);
// cos(a) to tg(a/2) 
double tg2c (const double cs);
// cos(a) to ctg(a/2) 
double ctg2c (const double cs); 

struct RenderItem {
   enum TYPE {
      RIT_NULL = 0,
      RIT_LABEL, 
      RIT_PSEUDO, 
      RIT_HYDROGEN, 
      RIT_HYDROINDEX, 
      RIT_ISOTOPE,
      RIT_CHARGESIGN, 
      RIT_CHARGEVAL, 
      RIT_RADICAL, 
      RIT_STEREOGROUP,
      RIT_VALENCE,
      RIT_AAM,
      RIT_CHIRAL,
      RIT_ATTACHMENTPOINT,
      RIT_ATOMID,
      RIT_TOPOLOGY
   };

   RenderItem();
   void clear();

   TYPE ritype;
   Vec2f bbp;
   Vec2f bbsz;
   Vec2f relpos;
   int color;
   bool highlighted;
};

struct TextItem : public RenderItem {
   void clear();
   Array<char> text;
   FONT_SIZE fontsize;
};

struct GraphItem : public RenderItem {
   enum TYPE {DOT, CAP, PLUS, MINUS};
   void clear();
   TYPE type;
};

struct AtomDesc {
   AtomDesc();
   void clear ();

   int tibegin, ticount;
   int gibegin, gicount;

   bool showLabel;
   bool showHydro;
   bool shiftLeft;
   bool isRGroupAttachmentPoint;
   bool fixed;
   Vec2f pos;
   Vec2f boundBoxMin;
   Vec2f boundBoxMax;
   int label;
   int queryLabel;
   int color;
   int stereoGroupType;
   int stereoGroupNumber;

   float leftMargin, rightMargin, ypos, height;
private:
   AtomDesc(const AtomDesc& ad);
};

struct BondEnd {
   BondEnd ();
   void clear ();

   Vec2f dir;
   Vec2f lnorm;
   Vec2f p; // corrected position
   float rcos;
   float rsin;

   // these are bond end ids in the _data.bondend array, NOT neighbor indices in the molecule!
   int rnei;
   int lnei; 

   float rang;
   float lcos;
   float lsin;
   int next;
   float lang;
   bool centered;
   int aid;
   int bid;
   float offset;
   bool prolong;
   int lRing;
   float width;

private:
   BondEnd (const BondEnd& be);
};

struct BondDescr : public Edge {  
   BondDescr ();

   DEF_ERROR("molrender bond description");

   void clear ();

   int getBondEnd (int aid) const;
         
   Vec2f norm, dir, vb, ve, center;
   float thickness;
   float bahs, eahs;

   bool inRing;
   bool aromRing;
   bool stereoCare;
   bool centered;
   bool lineOnTheRight;
   int stereodir;
   int type;
   int queryType;
   float length;
   int be1, be2;
   float extP, extN;
   int tiTopology;
   int topology;
private:
   BondDescr (const BondDescr& bd);
};

struct Ring {
   Ring ();
   void clear ();

   Array<int> bondEnds;
   Array<float> angles;
   int dblBondCount;
   bool aromatic;
   Vec2f center;
   float radius;

private:
   Ring (const Ring& r);
};

struct MoleculeRenderData {
   MoleculeRenderData ();
   void clear ();

   Array<AtomDesc> atoms;
   Array<BondDescr> bonds;
   ObjArray<Ring> rings;
   Array<BondEnd> bondends;
   ObjArray<TextItem> textitems;
   Array<GraphItem> graphitems;
   Array<int> aam;
   Array<int> reactingCenters;
   Array<int> inversions;
   Array<int> exactChanges;
private:
   MoleculeRenderData (const MoleculeRenderData& data);
};

class RenderSettings {
public:
   RenderSettings ();   
   void init (float sf);

   TL_CP_DECL(Array<double>, bondDashSingleOrAromatic);
   TL_CP_DECL(Array<double>, bondDashDoubleOrAromatic);
   TL_CP_DECL(Array<double>, bondDashAny);
   TL_CP_DECL(Array<double>, bondDashAromatic);

   float subFont;
   float labelInternalOffset;
   float lowerIndexShift;
   float bondLineWidth;
   float bondSpace;
   float labelFont;
   float boundExtent;
   float upperIndexShift;
   float radicalRightOffset;
   float radicalRightVertShift;
   float radicalTopOffset;
   float radicalTopDistDot;
   float radicalTopDistCap;
   float stereoGroupLabelOffset;
   float dashUnit;
   float eps;
   float stereoCareBoxSize;
   float cosineTreshold;
   float prolongAdjSinTreshold;
   float minBondLength;

   float fzz[FONT_SIZE_COUNT];

   // Layout params, relative to average bond length units
   float layoutMarginHorizontal;
   float layoutMarginVertical;
   float plusSize;
   float metaLineWidth;
   float arrowLength;
   float arrowHeadWidth;
   float arrowHeadSize;
   float equalityInterval;
   float rGroupSymbolFont;
   float rGroupLogicFont;
   float rGroupIfThenFont;
   float rGroupIfThenInterval;
   const char* fontPathRegular;
   const char* fontPathBold;

private:
   RenderSettings (const RenderSettings& settings);
};

struct CanvasOptions {
   CanvasOptions ();
   void clear ();
   
   int width;
   int height;
   int xOffset;
   int yOffset;
   float bondLength;
   float marginFactor;
};

struct HighlightingOptions {
   HighlightingOptions ();
   void clear();

   bool highlightThicknessEnable;
   float highlightThicknessFactor;
   bool highlightColorEnable;
   Vec3f highlightColor;
};

struct RenderContextOptions {
   RenderContextOptions ();
   void clear();

   Vec3f aamColor;
   float commentFontFactor;
};

class RenderOptions {
public:
   RenderOptions ();
   void clear();
   void copy(const RenderOptions& other);

   Array<char> comment;
   COMMENT_POS commentPos;
   ALIGNMENT commentAlign;
   Vec3f commentColor;
   LABEL_MODE labelMode;
   IMPLICIT_HYDROGEN_MODE implHMode;
   bool showBondIds;
   bool showBondEndIds;
   bool showNeighborArcs;
   bool showAtomIds;
   bool showValences;
   bool atomColoring;
   bool useOldStereoNotation;
   bool showReactingCenterUnchanged;
   bool centerDoubleBondWhenStereoAdjacent;
   bool showCycles; // for diagnostic purposes
private:
   RenderOptions (const RenderOptions& );
};

static bool ElementHygrodenOnLeft[] =
{
   false,  // filler
   false,  //ELEM_H
   false,  //ELEM_He
   false,  //ELEM_Li
   false,  //ELEM_Be
   false,  //ELEM_B 
   false,  //ELEM_C 
   false,  //ELEM_N 
   true,   //ELEM_O 
   true,   //ELEM_F 
   false,  //ELEM_Ne
   false,  //ELEM_Na
   false,  //ELEM_Mg
   false,  //ELEM_Al
   false,  //ELEM_Si
   false,  //ELEM_P 
   true,   //ELEM_S 
   true,   //ELEM_Cl
   false,  //ELEM_Ar
   false,  //ELEM_K
   false,  //ELEM_Ca
   false,  //ELEM_Sc
   false,  //ELEM_Ti
   false,  //ELEM_V
   false,  //ELEM_Cr
   false,  //ELEM_Mn
   false,  //ELEM_Fe
   false,  //ELEM_Co
   false,  //ELEM_Ni
   false,  //ELEM_Cu
   false,  //ELEM_Zn
   false,  //ELEM_Ga
   false,  //ELEM_Ge
   false,  //ELEM_As
   true,   //ELEM_Se
   true,   //ELEM_Br
   false,  //ELEM_Kr
   false,  //ELEM_Rb
   false,  //ELEM_Sr
   false,  //ELEM_Y
   false,  //ELEM_Zr
   false,  //ELEM_Nb
   false,  //ELEM_Mo
   false,  //ELEM_Tc
   false,  //ELEM_Ru
   false,  //ELEM_Rh
   false,  //ELEM_Pd
   false,  //ELEM_Ag
   false,  //ELEM_Cd
   false,  //ELEM_In
   false,  //ELEM_Sn
   false,  //ELEM_Sb
   false,  //ELEM_Te
   true,   //ELEM_I
   false,  //ELEM_Xe
   false,  //ELEM_Cs
   false,  //ELEM_Ba
   false,  //ELEM_La
   false,  //ELEM_Ce
   false,  //ELEM_Pr
   false,  //ELEM_Nd
   false,  //ELEM_Pm
   false,  //ELEM_Sm
   false,  //ELEM_Eu
   false,  //ELEM_Gd
   false,  //ELEM_Tb
   false,  //ELEM_Dy
   false,  //ELEM_Ho
   false,  //ELEM_Er
   false,  //ELEM_Tm
   false,  //ELEM_Yb
   false,  //ELEM_Lu
   false,  //ELEM_Hf
   false,  //ELEM_Ta
   false,  //ELEM_W
   false,  //ELEM_Re
   false,  //ELEM_Os
   false,  //ELEM_Ir
   false,  //ELEM_Pt
   false,  //ELEM_Au
   false,  //ELEM_Hg
   false,  //ELEM_Tl
   false,  //ELEM_Pb
   false,  //ELEM_Bi
   false,  //ELEM_Po
   false,  //ELEM_At
   false,  //ELEM_Rn
   false,  //ELEM_Fr
   false,  //ELEM_Ra
   false,  //ELEM_Ac
   false,  //ELEM_Th
   false,  //ELEM_Pa
   false,  //ELEM_U
   false,  //ELEM_Np
   false,  //ELEM_Pu
   false,  //ELEM_Am
   false,  //ELEM_Cm
   false,  //ELEM_Bk
   false,  //ELEM_Cf
   false,  //ELEM_Es
   false,  //ELEM_Fm
   false,  //ELEM_Md
   false,  //ELEM_No
   false   //ELEM_Lr
};

#endif //__render_common_h__